package avicit.bdp.dgs.mdm.service;

import avicit.bdp.common.utils.DateUtils;
import avicit.bdp.common.utils.redis.RedisCacheHelper;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dgs.mdm.dto.MdmRuleConfigDTO;
import avicit.bdp.dgs.mdm.utils.enums.MdmCodeTypeEnum;
import avicit.platform6.core.exception.BusinessException;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
public class DataCodeService {

  @Resource MdmRuleConfigService mdmRuleConfigService;

  @Resource RedisCacheHelper redisCacheHelper;

  /**
   * 生成编码数据
   *
   * @param ruleConfigId 码段规则ID
   * @param modelId 模型ID
   * @param filed 模型字段
   * @param dataMap 参数
   * @param increaseNum increaseNum
   * @return 编码数值
   * @throws Exception e
   */
  public String produceCode(
      String ruleConfigId,
      String modelId,
      String filed,
      Map<String, Object> dataMap,
      Integer increaseNum)
      throws Exception {

    String code = "";

    try {
      MdmRuleConfigDTO mdmRuleConfig = mdmRuleConfigService.queryById(ruleConfigId);
      if (mdmRuleConfig != null) {
        String blockVal = "";
        if (MdmCodeTypeEnum.GD.getCode().equals(mdmRuleConfig.getType())) {
          blockVal = mdmRuleConfig.getBlockVal();
          blockVal = StringEscapeUtils.unescapeHtml4(blockVal);
        } else if (MdmCodeTypeEnum.LS.getCode().equals(mdmRuleConfig.getType())) {
          blockVal = this.produceFlowCode(mdmRuleConfig, modelId, filed, increaseNum);
        } else if (MdmCodeTypeEnum.RQ.getCode().equals(mdmRuleConfig.getType())) {
          blockVal = this.produceDateCode(mdmRuleConfig, dataMap);
        } else {
          throw new BusinessException("编码配置暂不支持");
        }

        String preFix =
            mdmRuleConfig.getPreFix() == null
                ? ""
                : StringEscapeUtils.unescapeHtml4(mdmRuleConfig.getPreFix());
        String sufFix =
            mdmRuleConfig.getSufFix() == null
                ? ""
                : StringEscapeUtils.unescapeHtml4(mdmRuleConfig.getSufFix());
        code = code + preFix + blockVal + sufFix;
        return code;
      } else {
        throw new BusinessException("编码配置不存在");
      }
    } catch (Exception e) {
      throw new BusinessException(e.getMessage());
    }
  }

  private String produceFlowCode(
      MdmRuleConfigDTO mdmRuleConfig, String modelId, String filed, Integer increaseNum)
      throws Exception {

    StringBuilder flowCode;
    if (increaseNum == null) {
      increaseNum = 0;
    }

    int codeLen = mdmRuleConfig.getLength().intValue();
    int startVal = mdmRuleConfig.getStartVal().intValue();
    int step = mdmRuleConfig.getStep().intValue();

    String cacheKey = "DGS_MDM_MaxFlowNum_" + mdmRuleConfig.getId() + "_" + modelId + "_" + filed;
    String currentNumStr = redisCacheHelper.get(cacheKey);
    if (StringUtils.isNotBlank(currentNumStr)) {

      long currentNum = Long.parseLong(currentNumStr);

      StringBuilder maxValue = new StringBuilder();

      for (int i = 0; i < codeLen; ++i) {
        maxValue.append("9");
      }

      if (currentNum + (long) step + ((long) increaseNum * step)
          > Long.parseLong(maxValue.toString())) {
        throw new Exception("Exception_FlowCode_OutOfMaxValue");
      }

      BigInteger flowCodeVal = BigInteger.valueOf(currentNum + (long) step);
      flowCode = new StringBuilder(String.valueOf(flowCodeVal));
    } else {
      flowCode = new StringBuilder(String.valueOf(startVal + increaseNum * step));
    }

    redisCacheHelper.set(cacheKey, flowCode.toString());

    if (flowCode.length() >= codeLen) {
      flowCode = new StringBuilder(flowCode.substring(0, codeLen));
    } else {
      int countN = codeLen - flowCode.length();
      for (int i = 0; i < countN; ++i) {
        flowCode.insert(0, "0");
      }
    }

    return flowCode.toString();
  }

  private String produceDateCode(MdmRuleConfigDTO block, Map<String, Object> dataMap)
      throws Exception {

    String dateCode = "";
    String isCurrDate = block.getIsCurrDate();
    String dateType = block.getDateType();
    new Date();
    Date dateVal;

    if ("Y".equals(isCurrDate)) {
      dateVal = DateUtils.getCurrentDate();
    } else {
      String blockField = block.getBlockFid();
      String dateValStr = (String) dataMap.get(blockField);
      if (dateValStr == null) {
        dateValStr = "";
      }

      try {
        if ((!dateType.equalsIgnoreCase("yyyy") && !dateType.equalsIgnoreCase("yy")
                || dateValStr.length() < 4)
            && (!dateType.equalsIgnoreCase("yyyymm")
                    && !dateType.equalsIgnoreCase("yymm")
                    && !dateType.equalsIgnoreCase("mm")
                || dateValStr.length() < 7)
            && (!dateType.equalsIgnoreCase("yyyymmdd")
                    && !dateType.equalsIgnoreCase("yymmdd")
                    && !dateType.equalsIgnoreCase("mmdd")
                    && !dateType.equalsIgnoreCase("dd")
                || dateValStr.length() < 10)) {

          throw new Exception("Exception_DateFieldIsNotDateVal");
        }

        if (dateValStr.length() == 4) {
          dateValStr = dateValStr + "-01-01 00:00:00";
        } else if (dateValStr.length() == 7) {
          dateValStr = dateValStr + "-01 00:00:00";
        } else if (dateValStr.length() == 10) {
          dateValStr = dateValStr + " 00:00:00";
        }

        dateVal = DateUtils.parse(dateValStr, "yyyy-MM-dd HH:mm:ss");
      } catch (ParseException var13) {
        var13.printStackTrace();
        throw new Exception("Exception_DateFieldIsNotDateVal");
      }
    }

    if ("yyyy".equalsIgnoreCase(dateType)) {
      dateCode = DateUtils.format(dateVal, "yyyy");
    } else if ("yy".equalsIgnoreCase(dateType)) {
      dateCode = DateUtils.format(dateVal, "yyyy").substring(2, 4);
    } else if ("yyyymm".equalsIgnoreCase(dateType)) {
      dateCode = DateUtils.format(dateVal, "yyyy-MM").replace(Constants.SUBTRACT_STRING, "");
    } else if ("yymm".equalsIgnoreCase(dateType)) {
      dateCode =
          DateUtils.format(dateVal, "yyyy-MM")
              .replace(Constants.SUBTRACT_STRING, "")
              .substring(2, 6);
    } else if ("yyyymmdd".equalsIgnoreCase(dateType)) {
      dateCode = DateUtils.format(dateVal, "yyyy-MM-dd").replaceAll(Constants.SUBTRACT_STRING, "");
    } else if ("yymmdd".equalsIgnoreCase(dateType)) {
      dateCode =
          DateUtils.format(dateVal, "yyyy-MM-dd")
              .replaceAll(Constants.SUBTRACT_STRING, "")
              .substring(2, 8);
    } else if ("mm".equalsIgnoreCase(dateType)) {
      dateCode = DateUtils.format(dateVal, "MM");
    } else if ("mmdd".equalsIgnoreCase(dateType)) {
      dateCode =
          DateUtils.format(dateVal, "yyyy-MM-dd")
              .replaceAll(Constants.SUBTRACT_STRING, "")
              .substring(4, 8);
    } else if ("dd".equalsIgnoreCase(dateType)) {
      dateCode = DateUtils.format(dateVal, "dd");
    }

    return dateCode;
  }
}
